﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DotSpatial.Controls;
using DotSpatial.Data;
using DotSpatial.Topology;
using System.Data;

namespace GeostatisticalTool.Classes
{
   public class ConfigurationMethod 
    {
        private Map _map;
        public string PathFolder { set; get; }
        private double standarDev = 0;
        private SearchData search;
        private CheckDataInput check;

        private IFeatureSet data;
        private IFeatureSet _originalData;
        private ComboBox trend;
        private ListBox method;
        private ListBox output;
        private ComboBox layer;
        private ComboBox field;
        private ComboBox transformation;
        private bool filter;
        private string nameFilterField;
        public string FieldValue;
        public string TransformationValue;
        public CheckBox uxCheck;

        //private double[] error;
        //private double[] stdError;

        //public double[] StdError
        //{
        //    get { return stdError; }
        //    set { stdError = value; }
        //}


        #region Properties

        public CheckDataInput CheckData
        {
            get { return check; }
            set { check = value; }
        }
        public IFeatureSet OriginalData
        {
            get { return _originalData; }
            set { _originalData = value; }
        }



        public SearchData Search
        {
            get { return search; }
            set { search = value; }
        }


        public double StandarDev
        {
            get { return standarDev; }
            set { standarDev = value; }
        }

        public double MeanValue
        {
            get { return check.MeanValue; }
           
        }

        public String Method
        {
            get { return method.SelectedItem.ToString(); }
        }

        public String Layer
        {
            get { return this.layer.Text; }
        }


        public string Transformation
        {
          get {
              if (this.transformation == null)
              {
                  return "None";
              }
              else
              return transformation.Text; }

        }

        public int Trend
        {
            get {
                if (this.trend == null)
                {
                    return 0;
                }else
                return trend.SelectedIndex; }

        }

        public Map Map
        {
            get { return _map; }
            set { _map = value; }
        }


        public IFeatureSet Data
        {
            get { return data; }
            set { data = value; }
        }


        public string Field
        {
            get { return field.Text; }
        }
        #endregion


        public ConfigurationMethod( )
        {
        }


        public ConfigurationMethod(
          Map map
         )
        {
            this._map = map;
           
        }


        public ConfigurationMethod(
            Map map,
                               ListBox method,
                               ComboBox layer,
                               ComboBox field
            ) {
                this._map = map;
                this.method = method;
                this.layer = layer;
                this.field = field;
                UpdataLayer();

        }


        public ConfigurationMethod(
            Map map,
                               ListBox method,
                               ListBox output,
                               ComboBox layer,
                               ComboBox field,
                               ComboBox transformation,
                               ComboBox trend, bool filter )
        {
            this._map = map;
            this.method = method;
            this.output = output;
            this.layer = layer;
            this.field = field;
            this.transformation = transformation;
            this.trend = trend;
            this.filter = filter;

            if (filter)
                UpdataLayerFilter();
            else
                UpdataLayer();

            this.method.SelectedValueChanged += new EventHandler(method_Click);
            this.trend.SelectedValueChanged+= new EventHandler(trend_Click);
        }

       public void SetField()
        {

        }

       public void SetParameters(
            Map map,
            ListBox method,
            ListBox output,
            ComboBox layer,
            ComboBox field,
            ComboBox transformation,
            ComboBox trend, bool filter)
       {
           this._map = map;
           this.method = method;
           this.output = output;
           this.layer = layer;
           this.field = field;
           this.transformation = transformation;
           this.trend = trend;
           this.filter = filter;
           this.method.SelectedValueChanged += new EventHandler(method_Click);
           this.trend.SelectedValueChanged += new EventHandler(trend_Click);
       }



        private void method_Click(object sender, EventArgs e) {

            if (method.Text == "Simple Kriging")
            {
                this.trend.SelectedIndex = 1;
                this.trend.Enabled = true;
            }
            if (method.Text == "Universal Kriging")
            {
                this.trend.SelectedIndex = 0;
                this.trend.Enabled = false;
            }

            if (method.Text == "Ordinary Kriging")
            {
                this.trend.SelectedIndex = 0;
                this.trend.Enabled = true;
            }

        
        }

        private void trend_Click(object sender, EventArgs e)
        {
            if (trend.Text == "None" && method.Text == "Simple Kriging")
            {
                this.trend.SelectedIndex = 1;
            }
        }


        private void UpdataLayerFilter()
        {

            foreach (IMapLayer ila in this._map.GetPointLayers())
            {
                IFeatureSet fT = (IFeatureSet)ila.DataSet;
                if (ila.LegendText.ToUpper() == "Measure".ToUpper())
                {
                    _originalData = fT;
                    this.layer.Items.Add(ila.LegendText);
                }

            }
            if (_originalData == null)
                return;

            this.layer.SelectedIndex = 0;
            this.layer.Enabled = false;
            SortedList<string, string> list = new SortedList<string, string>();
            foreach (DataRow row in _originalData.DataTable.Rows)
            {

                if (!list.ContainsKey(Convert.ToString(row["Variable"])))
                {
                    list.Add(Convert.ToString(row["Variable"]), Convert.ToString(row["Variable"]));

                }
            }
            this.field.Items.Clear();

            foreach (string d in list.Keys)
                this.field.Items.Add(d);

        }





        private void UpdataLayer()
        {

            if (this.layer == null) return;

            int i = 0;
            foreach (IMapLayer ila in this._map.GetPointLayers())
            {
                IFeatureSet fT = (IFeatureSet)ila.DataSet;
                    if (i == 0)
                    {
                        _originalData = fT;
                        UpdateField();
                    }
                    if (ila!=null) 
                         this.layer.Items.Add(ila.LegendText);
                    i++;
            }

            foreach (IMapLayer ila in this._map.GetLineLayers())
            {
               
                IFeatureSet fT = (IFeatureSet)ila.DataSet;
                if (i == 0)
                {
                    _originalData = fT;
                    UpdateField();
                }
                if (ila != null)
                    this.layer.Items.Add(ila.LegendText);
                i++;
            }



            foreach (IMapGroup ila1 in this._map.MapFrame.GetAllGroups())
            {
                foreach (IMapLayer ila in ila1)
                {


                    IFeatureSet fT;
                    try
                    {
                        fT = (IFeatureSet)ila.DataSet;
                    }
                    catch
                    {
                        continue;
                    }
                    if (fT == null)
                        break;
                    if (fT.FeatureType == FeatureType.Point)
                    {
                        if (i == 0)
                        {
                            _originalData = fT;
                            UpdateField();
                        }

                        if (ila != null)
                            this.layer.Items.Add(ila.LegendText);
                        i++;
                    }
                }
            }

            if (this.layer.Items.Count > 0)
                this.layer.SelectedIndex = 0;
            else
                return;

            this.layer.SelectedIndexChanged += Layer_Click;
        }

        private void UpdateField()
        {
            this.field.Items.Clear();
            foreach (DataColumn col in _originalData.DataTable.Columns)
            {
                if (col.DataType == typeof(double) ||
                    col.DataType == typeof(int) ||
                    col.DataType == typeof(Int16) ||
                    col.DataType == typeof(Int32) ||
                    col.DataType == typeof(Int64))
                    this.field.Items.Add(col.ColumnName);
            }
            if (this.field.Items.Count > 0)
                this.field.SelectedIndex = 0;
        }

        private void Layer_Click(object sender, EventArgs e)
        {
            foreach (IMapLayer ila in this._map.GetPointLayers())
            {
                if (ila.LegendText == this.Layer)
                {
                    this._originalData = (IFeatureSet)ila.DataSet;
                    break;
                }
            }

            foreach (IMapLayer ila in this._map.GetLineLayers())
            {
                if (ila.LegendText == this.Layer)
                {
                    this._originalData = (IFeatureSet)ila.DataSet;
                    break;
                }
            }



            UpdateField();
        }

        public bool Load(int num)
        {

            if (_originalData.FeatureType == FeatureType.Line)
                _originalData = ConvertToPoints(_originalData);

            if (this.field == null || this.Transformation == null)
            {
                check = new CheckDataInput(_originalData, FieldValue, TransformationValue, this.filter);
            }
            else
            {
                check = new CheckDataInput(_originalData, Field, Transformation, this.filter);
            }
            string[] values = check.LoadPoints(uxCheck.Checked);

            this.data = check.data;

            if (data == null) return false;

            if (data.Features.Count < num)
            {
                MessageBox.Show("It is require at least " + num.ToString()+" points");
                return false;
            }


            if (values[1] != null)
            {
                MessageBox.Show("Transformation problem (Not zero values allowed)");
                return false;
            }

            if (values[0] != null)
            {
                MessageBox.Show("The mean will be applied in the duplicate points ");
                return true;
            }

            return true;

        }
        public bool Load()
        {
            if (_originalData.FeatureType == FeatureType.Line)
                _originalData = ConvertToPoints(_originalData);


            if (this.field == null || this.Transformation == null)
            {
                check = new CheckDataInput(_originalData, FieldValue, TransformationValue, this.filter);
            }
            else
            {
                check = new CheckDataInput(_originalData, Field, Transformation, this.filter);
            }
            string[] values = check.LoadPoints(!uxCheck.Checked);

            this.data = check.data;

            if (data == null) return false;

            if (data.Features.Count < 7)
            {
                MessageBox.Show("It is needed more than seven points");
                  return false;
            }
            if (values.Length == 0) return true;
            if (values[1] != null)
            {
                MessageBox.Show("Transformation problem (Not zero values allowed)");
                return false;
            }

            if (values[0] != null)
            {
                MessageBox.Show("The mean will be applied in the duplicate points ");
                return true;
            }

            return true;
        }

        private IFeatureSet ConvertToPoints(IFeatureSet originalData)
        {
            string field= Field;
            IFeatureSet fea = new FeatureSet(FeatureType.Point);
            fea.Projection = originalData.Projection;
            DataColumn col = originalData.GetColumn(field);
            DataColumn coln= new DataColumn(col.ColumnName, col.DataType);
            fea.DataTable.Columns.Add(coln);

            foreach (Feature feature in originalData.Features)
            {
                foreach (Coordinate c in feature.BasicGeometry.Coordinates)
                {
                    IFeature nfeature = fea.AddFeature(new DotSpatial.Topology.Point(c.X,c.Y));
                    nfeature.DataRow[field] = feature.DataRow[field];

                }
            
            
            }
            return fea;


        }

        public bool Load(string filter)
        {

            if (_originalData.FeatureType == FeatureType.Line)
                _originalData = ConvertToPoints(_originalData);



            CheckDataInputFilter check;
            if (this.field == null || this.Transformation == null)
            {
                check = new CheckDataInputFilter(_originalData, FieldValue, TransformationValue, this.filter);
            }
            else
            {
               check = new CheckDataInputFilter(_originalData, Field, Transformation, this.filter);
            }


          // CheckDataInputFilter check = new CheckDataInputFilter(_originalData, Field, Transformation, this.filter);
           check.Filterfields = filter;
           string[] values = check.LoadPoints(uxCheck.Checked);
            this.check = check;
            this.data = check.data;

            if (data == null) return false;

            if (data.Features.Count < 7)
            {
                MessageBox.Show("It is needed more than seven points");
                return false;
            }

            if (values[1] != null)
            {
                MessageBox.Show("Transformation problem (Not zero values allowed)");
                return false;
            }

            if (values[0] != null)
            {
                MessageBox.Show("The mean will be applied in the duplicate points ");
                return true;
            }

            return true;
        }

        public void RemoveTrend(int idFieldToApplyTrend,Trend trend)
        {
            foreach (Feature fea1 in data.Features)
            {
                double[] value = trend.Interpolate(fea1.Coordinates[0].X, fea1.Coordinates[0].Y, fea1.Coordinates[0].Z,true);
                fea1.DataRow["Trend"] =value[0];
                fea1.DataRow["Used"] = Convert.ToDouble(fea1.DataRow[idFieldToApplyTrend]) - value[0];
            }
        }

        public void UpdateWorkField(int idFieldToWork)
        {

            foreach (Feature fea1 in data.Features)
            {
                fea1.DataRow["Used"] = fea1.DataRow[idFieldToWork];
            }
        }

    
    }
}
